<!--
 * @Date: 2024-03-11 17:20:49
 * @Autor: 叶世超
 * @LastEditors: 叶世超 yesc163@163.com
 * @LastEditTime: 2024-04-12 10:00:55
 * @FilePath: \reslib-web\src\views\knowledge\extraction\index.vue
 * @Description: 实体提取
 * @version: 版本
-->
<template>
  <div class="extraction">
    <!-- <ContentWrap>实体提取</ContentWrap> -->
    <ContentWrap>
      <div class="e-content">
        <div class="ec-textarea">
          <el-input v-model="textarea" style="width: 100%; margin-bottom: 20px" :autosize="{ minRows: 8, maxRows: 8 }"
            resize="none" type="textarea" placeholder="请输入实体内容" />
          <el-button @click="submitForm" type="primary" size="large">提交文本</el-button>
        </div>
        <div v-if="plo.length" class="ec-top">
          <div class="ect-title">实体识别</div>
          <div class="ect-content">
            <div class="ecm-left">
              <div v-html="entityRecognition"> </div>
            </div>
            <div class="ecm-right">
              <div class="er-button">
                <el-button @click="selectedTab(item.type)" v-for="(item, index) in tabsList" :key="index"
                  :color="colorObject[item.type]" :dark="true">
                  {{ item.text }}</el-button>
              </div>
              <div v-for="(value, key, index) in ploResult" class="er-form">
                <el-form v-for="(it, ind) in value" :key="ind" :inline="true" :model="formInline"
                  class="demo-form-inline">
                  <el-form-item v-if="activeName == key" label="">
                    <el-input v-model="it.word" placeholder="" clearable />
                    <el-button type="primary" @click="ploAdd(index, ind)">选词填入</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </el-form-item>
                </el-form>
              </div>
            </div>
          </div>
        </div>
        <div v-if="qk.length" class="ec-middle">
          <div class="ecm-title">事件抽取</div>
          <div v-for="(item, index) in qk" :key="index" class="table-box">
            <el-button type="info" size="large">移除</el-button>
            <table class="">
              <thead>
                <tr>
                  <td>项目</td>
                  <td>值</td>
                  <td>操作</td>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>所在句子</td>
                  <td>{{ item.sentence }}</td>
                  <td></td>
                </tr>
                <tr>
                  <td>事件描述</td>
                  <!-- <td>{{ item.desc }}</td> -->
                  <td class="td-input">
                    <input v-model="item.desc" type="text" placeholder="" />
                  </td>
                  <td class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">编辑</el-button>
                  </td>
                </tr>
                <tr>
                  <td>相关人物</td>
                  <!-- <td>{{ item.persons }}</td> -->
                  <td class="td-input">
                    <input v-model="item.persons" type="text" placeholder="" />
                  </td>
                  <td class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">添加</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </td>
                </tr>
                <tr v-for="(it, ind) in item.tags" :key="ind">
                  <td>{{ it.tagType }}</td>
                  <td class="td-input">
                    <input v-if="it.tagType !== '发生时间'" v-model="it.word" type="text" placeholder="" />
                    <!-- <el-date-picker v-if="it.tagType === '发生时间'" v-model="it.word" type="date" placeholder="Pick a day" size="default" /> -->
                    <!-- <input v-if="it.tagType === '发生时间'" v-model="it.word" type="date" placeholder="Pick a day" size="default" /> -->
                    <input v-if="it.tagType === '发生时间'" v-model="it.word" type="date" placeholder="Pick a day"
                      size="default" />
                  </td>
                  <!-- <td>{{ it.word }}</td> -->
                  <!-- <input v-model="it.word" type="text" placeholder="" /> -->
                  <td v-if="it.tagType == '事件动词描述'" class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">编辑</el-button>
                  </td>
                  <td v-if="it.tagType == '事件动词'" class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">编辑</el-button>
                  </td>
                  <td v-if="it.tagType == '发生时间'" class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">时间选择器</el-button>
                  </td>
                  <td v-if="it.tagType == '发生地点'" class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">选词填入</el-button>
                  </td>
                  <td v-if="it.tagType == '施事者'" class="td-operate">
                    <el-button type="primary" @click="onSubmit(index)">添加</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        <div v-if="rdf.length" class="ec-bottom">
          <div class="ecb-title">关系抽取</div>
          <div v-for="(item, index) in rdf" :key="index" class="table-box">
            <el-button @click="rdfDelete(index)" type="info" size="large">移除</el-button>
            <table class="">
              <thead>
                <tr>
                  <td>项目</td>
                  <td>值</td>
                  <td>操作</td>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>句子</td>
                  <td>{{ item.sen }}</td>
                  <td></td>
                </tr>
                <tr>
                  <td>实体</td>
                  <td class="td-input">
                    <input v-model="item.entity" type="text" placeholder="" />
                  </td>
                  <td class="td-operate">
                    <el-button type="primary" @click="rdfAdd(index)">添加</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </td>
                </tr>
                <tr>
                  <td>实体</td>
                  <td class="td-input">
                    <input v-model="item.feature" type="text" placeholder="" />
                  </td>
                  <td class="td-operate">
                    <el-button type="primary" @click="rdfAdd">添加</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </td>
                </tr>
                <tr>
                  <td>关系</td>
                  <td class="td-input">
                    <input v-model="item.relationship" type="text" placeholder="" />
                  </td>
                  <td class="td-operate">
                    <el-button type="primary" @click="rdfAdd">选词填入</el-button>
                    <!-- <el-button type="info" @click="">移除</el-button> -->
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </ContentWrap>
  </div>
</template>
<script lang="ts" setup>
import * as FormApi from '@/api/knowledge/extraction'
import FormatDate from '@/utils/dateFormat'
const formInline = reactive({
  user: '',
  region: '',
  date: ''
})
const onSubmit = (index) => {
  //   {
  //     "graphName": "测试xml2",
  //     "graphId": "af9a743f980b48c6b57306327d3b63c5",
  //     "entityType": "2",
  //     "id": "98db767437c64d23aad330adea43d59f",
  //     "sentence": "0001",
  //     "desc": "0001",
  //     "persons": "0001",
  //     "orgs": "0001",
  //     "verbDescription": "0001",
  //     "eventVerb": "0001",
  //     "eventDate": "2024-04-10T16:00:00.000Z",
  //     "eventLocation": "0001",
  //     "recipient": "0001",
  //     "agent": "0001",
  // }
  const params2 = {
    "graphName": "测试xml2",
    "graphId": "af9a743f980b48c6b57306327d3b63c5",
    "entityType": "2",
    "id": "98db767437c64d23aad330adea43d59f",
    sentence: "",
    desc: "",
    persons: "",
    "orgs": "0001",
    verbDescription: "",
    eventVerb: "",
    eventDate: "",
    eventLocation: "",
    recipient: "",
    agent: "",
  }
  console.log(index)
  console.log(qk)
  console.log(qk[index])
  // for (const item in qk[index]) {
  // console.log(item)
  console.log(qk[index].desc)
  params2.desc = qk[index].desc
  params2.persons = qk[index].persons
  params2.sentence = qk[index].sentence
  console.log(qk[index].tags)
  qk[index].tags.forEach(element => {
    console.log(element)
    if (element.tagType == '事件动词') params2.eventVerb = element.word
    if (element.tagType == '事件动词描述') params2.verbDescription = element.word
    if (element.tagType == '发生时间') params2.eventDate = element.word
    if (element.tagType == '发生地点') params2.eventLocation = element.word
    if (element.tagType == '施事者') params2.recipient = element.word
    if (element.tagType == '受事者') params2.agent = element.word
  })
  // }
  console.log('submit!')

  FormApi.updateHybaseGraphEvent(params2).then((res) => {
    console.log(res)
  })
}
const inputStyle = {
  border: 'none!important',
  height: '50px'
}
// 实体识别类型字段映射
const ploMapping = { 1: 1001, 2: 1002, 3: 1003, 4: 1010, 5: 1020, 6: 2001 }
const ploAdd = (index, ind) => {
  console.log(index, ind)
  const params = []
  console.log(ploResult)
  console.log(ploResult[ploMapping[index + 1]][ind])
  params.push({
    word: ploResult[ploMapping[index + 1]][ind].word,
    entityName: '实体抽取',
    entityResources: '实体抽取2',
    entityType: index + 1,
    graphId: 'af9a743f980b48c6b57306327d3b63c5',
    graphName: '测试xml2'
  })
  FormApi.insertGraphEntityByList(params).then((res) => {
    console.log(res)
  })
}
const rdfAdd = (index) => {
  const params = []
  rdf.forEach((it, ind) => {
    params.push({
      feature: rdf[ind].feature,
      relation: rdf[ind].relationship,
      sen: rdf[ind].sen,
      entity: rdf[ind].entity,
      graphName: '测试图谱知识库'
    })
  })
  FormApi.insertNeo4j(params).then((res) => {
    console.log(res)
  })
}
const rdfDelete = (index) => {
  console.log(rdf[index])
  Object.keys(rdf[index]).forEach((key) => (rdf[index][key] = ''))
  console.log(rdf[index])
  const params = []
  rdf.forEach((it, ind) => {
    if (ind === index) return
    params.push({
      feature: rdf[ind].feature,
      relation: rdf[ind].relationship,
      sen: rdf[ind].sen,
      entity: rdf[ind].entity,
      graphName: '测试图谱知识库'
    })
  })
  FormApi.insertNeo4j(params).then((res) => {
    console.log(res)
  })
}

const textarea = ref<String>('')
// pro接口返回数据
var plo = reactive<Array>([])
const qk = reactive<Array>([])
const rdf = reactive<Array>([])
textarea.value =
  '习近平主席特使、全国人大常委会副委员长艾力更·依明巴海2019年12月10日在阿根廷首都布宜诺斯艾利斯出席阿新总统就职仪式，并于9日会见新任总统费尔南德斯。艾力更·依明巴海向费尔南德斯转达了习近平主席的热烈祝贺和良好祝愿，并转交了习主席亲署函。艾力更·依明巴海表示，中方始终从战略高度和长远角度发展对阿关系，愿同阿方携手努力，加强全方位交往，推进各领域互利合作，密切人文领域交流，深化多边战略协作，推动中阿全面战略伙伴关系深入发展。费尔南德斯感谢习近平主席派特使出席其就职仪式，请艾力更·依明巴海转达他对习近平主席的亲切问候。费表示，读了习主席亲署函，感到非常高兴和亲切。阿新政府高度重视对华关系，对两国合作充满信心和期待，愿同中方携手努力，深化各领域交往与合作，将两国关系提升到新的高度。艾力更·依明巴海还会见了阿新任副总统克里斯蒂娜和卸任总统马克里'
// 实体识别结果
const entityRecognition = ref<String>('')
// const colorArray = ['#fff39a', '#8ed3d4', '#ffcb99', '#ffcccb', '#67ccaa', '#50c6fb', '#cccccc', '#8ea4de', '#d07f7f', '#9acccd', '#99cc67', '#800080', '#cd4200']
// 1001-人名、1002-地名、1003-组织名、1010-职务、1020-国家、2001-时间
const colorObject: Object = {
  1001: '#fff39a',
  1002: '#ff8c8c',
  1003: '#e99d42',
  1010: '#8ed3d4',
  1020: '#ccff89',
  2001: '#ffcccb'
}
// console.log(entityRecognition.value)
const tabsList = [
  { type: 1001, text: '人名' },
  { type: 1002, text: '地名' },
  { type: 1003, text: '组织名' },
  { type: 1010, text: '职务' },
  { type: 1020, text: '国家' },
  { type: 2001, text: '时间' }
]
const ploForm = []
const keywordsFcn = (text, key) => {
  // console.log(key)
  key.forEach((item, index) => {
    const regex = new RegExp(item.word, 'g')
    entityRecognition.value = entityRecognition.value.replace(
      regex,
      (match) =>
        `<span style="background-color:${colorObject[item.type]
        };margin:2px;padding:2px; display: inline-block;font-size: 14px;">${match}</span>`
    )
  })
  // console.log(entityRecognition.value)
}
let activeName = ref<Number>(1001)
const selectedTab = (type) => {
  activeName.value = type
  console.log(activeName)
}
// const formInline = []
var ploResult = {}
// 转换为二维
const convertToTwoDimensional = (oneDimensionalArray, idKey) => {
  const twoDimensionalObject = {}
  oneDimensionalArray.forEach((item) => {
    const id = item[idKey]
    if (!twoDimensionalObject[id]) {
      twoDimensionalObject[id] = []
    }
    twoDimensionalObject[id].push(item)
  })
  return twoDimensionalObject
}
function convertDate(dateStr) {
  const parts = dateStr.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
  if (parts) {
    const year = parts[1];
    const month = String(parts[2]).padStart(2, '0');
    const day = String(parts[3]).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }
  return null;
}
// 示例使用
const originalDateStr = "2023年03月15日";
const convertedDateStr = convertDate(originalDateStr);
console.log(convertedDateStr); // 输出: 2023-03-15
const submitForm = () => {
  entityRecognition.value = textarea.value
  // 实体识别
  FormApi.plo(textarea.value).then((res) => {
    Object.assign(plo, JSON.parse(res))
    plo = plo.sort((a, b) => {
      return b.word.length - a.word.length
    })
    console.log('plo', plo)
    ploResult = convertToTwoDimensional(plo, 'type')
    keywordsFcn(textarea, plo)
    console.log(ploResult)
  })
  // 事件抽取
  FormApi.qk(textarea.value).then((res) => {
    Object.assign(qk, JSON.parse(res))
    for (const item of qk) item.persons = item.persons.join(',').replace(/,/g, ';')
    console.log('qk', qk)
    qk.forEach(item => {
      item.tags.forEach(element => { if (element.tagType == '发生时间') element.word = convertDate(element.word) })
    })
  })
  // 关系抽取
  FormApi.rdf(textarea.value).then((res) => {
    Object.assign(rdf, JSON.parse(res))
    console.log('rdf：', rdf)
  })
}
</script>
<style lang="scss" scoped>
.td-operate {
  display: flex;

  ::v-deep(.el-button) {
    margin-bottom: 0px !important;
  }
}

.td-input {
  padding: 0 !important;

  input {
    border: none;
    outline: none;
    width: 100%;
    height: 50px;
    box-sizing: border-box;
    padding-left: 10px;
    font-size: 16px;
  }
}

.extraction {
  .e-content {
    .ec-textarea {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: flex-end;
    }

    .ec-top {
      .ect-title {
        font-size: 18px;
        font-weight: bold;
        padding-bottom: 20px;
      }

      .ect-content {
        display: flex;
        // justify-content: center;
        align-items: self-start;

        .ecm-left {
          div {
            background-color: #f6f6f6;
            padding: 30px 10px;
          }
        }

        .ecm-right {
          margin-left: 10px;

          .er-button {
            display: flex;
            margin-bottom: 18px;

            .el-button {
              margin-left: 0;
              border-radius: 0;
              padding: 0 20px;
            }
          }

          ::v-deep(.el-form-item) {
            width: 100%;
          }

          ::v-deep(.el-form-item__content) {
            width: 100%;
            display: flex;
            justify-content: center;

            // align-items: center;
            .el-input {
              margin-right: 12px;
            }
          }
        }
      }
    }

    .table-box {
      margin: 10px 0;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      align-items: flex-end;

      .el-button {
        width: 100px;
        margin-bottom: 10px;
      }

      table {
        width: 100%;
        border: 1px solid #cccccc;
        border-collapse: collapse;

        thead {
          tr {
            td:nth-child(1) {
              width: 200px;
            }

            td:nth-child(2) {
              flex: 1 !important;
            }

            td:nth-child(3) {
              width: 200px;
            }
          }
        }

        td {
          border: 1px solid #cccccc;
          padding: 10px;
        }
      }
    }

    .ec-middle {
      position: relative;

      .ecm-title {
        position: absolute;
        top: 8px;
        font-size: 18px;
        font-weight: bold;
      }
    }

    .ec-bottom {
      position: relative;

      .ecb-title {
        position: absolute;
        top: 8px;
        font-size: 18px;
        font-weight: bold;
      }
    }
  }
}

::v-deep(.el-table-v2__header-cell) {
  border: 1px solid #dbdbdb;
}

.demo-form-inline .el-input {
  --el-input-width: 220px;
}
</style>
